/*
Hermes Core: General Purpose Mobile Agent Platform
Copyright (C) 2006 UNICAM - Università degli Studi di Camerino

Group leaders: Flavio Corradini and Emanuela Merelli

Developers: Ezio Bartocci, Diego Bonura, Rosario Culmone,
Davide Lorenzoli, Leonardo Mariani, Francesca Piersigilli, 
Lorenzo Scortichini, Leonardo Vito.

GNU Lesser Public License

This library is free software; you can redistribute it 
and/or modify it under the terms of the GNU Lesser General 
Public License as published by the Free Software Foundation, 
version 2.1 of the License.

This library is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU Library General Public License for more details.

You should have received a copy of the GNU Library General Public 
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.

Emanuela Merelli
Dipartimento di Matematica ed Informatica
Università di Camerino
via Madonna delle Carceri, 62032 Camerino, Italy
E.Mail: emanuela.merelli@unicam.it
*/
package hermesV2;

import hermesV2.agent.Agent;
import hermesV2.agent.UserAgent;

import hermesV2.util.HermesLogger;

import java.lang.reflect.InvocationTargetException;


/**
 * It is the thread that represents the execution of the Agent. It's created
 * every time a new agent is created or enter in the system by a migration. It
 * has the responsability to manage the init of new agent or the call of the
 * callback method.
 *
 * @author Diego Bonura
 */
public class AgentThread extends Thread {
    /** The agent associated with the AgentThread. */
    private Agent agent;

    /** Represents the way to start the Agent. */
    private int mode;

    /**
     * Builds a new <code>AgentThread</code> that execute the given agent.
     *
     * @param agent the agent to execute.
     * @param mode the way to execute the given agent.
     */
    public AgentThread(Agent agent, int mode) {
        super();
        this.agent = agent;
        this.mode = mode;
    }

    /**
     * Returns the executing agent or null if the agent is not set.
     *
     * @return the executing agent or null if the agent is not set.
     */
    public Agent getAgent() {
        return agent;
    }

    /**
     * Starts the execution of the AgentThread and call the specific Agent
     * method respecting the mode parameter.
     */
    public void run() {
        try {
            if (agent != null) {
                switch (mode) {
                case Agent.INIT: {
                    agent.init();

                    break;
                }

                case UserAgent.RESTART: {
                	restartAgent();
                    break;
                }

                case UserAgent.CLONE: {
                    try {
                        ((UserAgent)agent).cloneback();
                    } catch (Exception e) {
                        HermesLogger.log(HermesLogger.WARNING, "Clone Exception", e);
                    }

                    break;
                }
                }
            }

            agent.dead();
        } catch (ThreadDeath td) {
            HermesLogger.log(HermesLogger.DEBUG, "AgentThread: Agent stopped by ThreadDeath exception");
        }
    }
    
    
    /**
     *  Restats the execution of an agent after a migration
     */
    public void restartAgent(){
    	try {
            ((UserAgent)agent).callback();
        } catch (IllegalAccessException iae) {
            HermesLogger.log(HermesLogger.WARNING, "IllegalAccessException", iae);
        } catch (InvocationTargetException ite) {
            HermesLogger.log(HermesLogger.WARNING, "InvocationTargetException", ite);
        } catch (NoSuchMethodException nsme) {
            HermesLogger.log(HermesLogger.WARNING, "NoSuchMethodException", nsme);
        }

    }

    
}
